RESTful APIのEndpointの設計
参考
基本的なことの列挙
基本的すぎるものもあるが、参考になるものもあった
良くないAPI
指定するパラメータが多い
引数の多い関数が扱いづらいのと同じだなmrsekut.icon
取得したデータの項目数が多い
返り値がごちゃごちゃしている関数が扱いづらいのと同じだなmrsekut.icon
大は小を兼ねるかもしれないが、client側のコストも上がる
含まれている、関係ないパラメータについても理解しないといけない
clientで利用するために、データの整形をしないといけない
登録時に、指定しなければいけないデータ項目が多い
これはUIにも依存しそうmrsekut.icon
現状はclientと1対1対応しているけど、今後のことを考えれば多少大きくしておいたほうがいいのか?みたいな迷いが出ることがあるmrsekut.icon
APIも過不足ないぐらいにしておくべきなのかどうか難しい
リソースの単位を分ける
データの塊を分ける
リクエスト数めっちゃ増えてしまわない?
常にこうしろ、という話ではないかmrsekut.icon
かといって、clientのことを考えて大きくすると、
ごちゃごちゃする
修正しづらい
clientと密結合になる
片方を修正すると、もう片方も全て修正が必要
APIを良くするために細かくするのはパフォーマンス的にどうなのか?
1requestで画面すべての情報を取得するのと、
3requestに分けるのと、どれぐらい差があるのか?
大して差がないのであれば、小さく作るべきだと思うけどmrsekut.icon
組み立ての多様性を維持しつつ、組み立ての負担が増えすぎない適切な大きさの部品を用意する
返却するもののサイズが小さいと、組み合わせによって多様なモノを表現できるが、clientで「組合立て処理」が必要になるので、その分複雑になる
大きいと、組み立て処理が不要だが、できることは単純になる
このバランスを取ろうという感じ
APiのresponseと、clientのdomain modelは関心が異なる
『現場で役立つシステム設計の原則』.iconp.255~
responseは、データ指向
Domainはclass指向だったりする
これはOOPを使っているのが悪いmrsekut.icon
必要なら、
Domain → ResClass
ReqClass → Domain
のような2つのclass(Res, Req)を用意する
返り値は導出データか生データか
マスタ項目のコードと名称
コードというのはidてきなもののことを指している
都道府県のデータをやり取りする時に
北海道のコード01
北海道の名称"北海道"
のどちらを含めるか
北海道objectのようなデータを返す時に、どちらを含めるかという話?
いまいちわからん
合計の計算
e.g. 年齢が欲しい場合に、生年月日を返すか、年齢を返すか
日付データの形式
日付と時刻は別の項目にすべき
タイムゾーンの解釈違いを避けるため
clientとserverが両方ともJSで、同じlibraryを使えるなら問題はなさそうmrsekut.icon
APIを3種類に分けて考える
責務を3種類にわけようという話
コアとなる基本API
めちゃくちゃ小さい単位のAPI
これを組み合わせればどのclientの都合にも対応はできる
ただし、client側で組み合わせる必要がある
拡張API
コアとなる基本APIをもう少し大きな塊にしたもの
これもどのclientの都合にも対応できるようにする
個別対応API
特定の利用者の特定のニーズのみに対応するぐらいの、ちょい大きめのもの
clientと1対1対応になる
endpointに自分のuserIdとかを含めるとcacheできない
まあでもuserIdが入っているものはshared cacheにすべきなものではないmrsekut.icon
これも結局はresponseがでかいことが原因
userIdが必要なものと、そうでないものをちゃんと分けるべき
例えば、投稿の中に「いいね」が含まれているようなページを表示する時に、
投稿のresponseの中に、いいねを含めない
全員が共有して見れる投稿の内容と、いいね情報は分けてAPIにすべき
どこまで汎化させるか問題
clientは、その中で閉じて作ればいい
ほかから使用されることがないので汎化させる必要がない
修正が出てくればその閉じた中で作ればいいだけ
serverはちょっと特殊
複数のclientから参照される
古いアプリを使っているユーザーのことを考えれば、古い実装も残し続ける必要がある
多くのものに依存されるので修正が困難になる
例えば、contestsというのがあったとして
openとcloseというstatusがあった時に、
open全部、close全部、openとclose全部、を取得したいというケースを想定すれば
statuses=[open, close]のようなインターフェースにすれば賄うことができる
clientは、RESTを通してqueryを書いているような感じになる
これは、openもcloseもclientで使っているので実装に迷いがない
では、contests/tagsというのがあったとする
今のclientでは、openなものしか必要としていない
この時に、contestsと同じように、/contests/tags?sutatues=[..]のようにするのか、
/contests/tags/openとするのかという迷いが生じる
これを選んだ時に、あとからcloseもほしい、となった場合
これとは別に、/contests/tags?sutatues=[..]を作ることになる
まあこの考え方は本当はおかしいかmrsekut.icon
考え方が逆
どう使われるか、ではなく、そのendpoint自体がどういう責務を担っているのか、みたいな話か?
いやいうほど逆でもない気もするmrsekut.icon
誰にも使われていないqueryをserver上でメンテし続けないといけなくなる
requesut回数が多いのAPIの蔑称
おしゃべりなAPI
732ページ
Web APIのデザイン
基本的にAPIの結果はは正規化するけど、expand=を付けた時は、正規化しないってことかmrsekut.icon
用途に依って使い分けることができる
backendの実装が大変になりそうmrsekut.icon
修正が必要になった時に修正箇所が増えそうmrsekut.icon
micrsoft
日本語